#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <iostream>

#include "Update.h"
#include "GLOBALS.h"

using namespace std;

// ALL THE INPUT FUNCTIONS

  int update_all(enum input_type keypressed){
    int gameExit=0;
    
    moveSnake(keypressed);
    gameExit=hitDetect();
    spawnFood();
    
    return gameExit;
  }
  
  
// This function moves the snake into a new direction and updates all the parts of the snake. If the snake is not yet present, it places it then.
void moveSnake(enum input_type key){
  if(sSnake.is_initialized==0){
    cout << "Initializing a new snake..." << endl;
    
    //initialize element 0
    sSnake.body[0].cordX=10;
    sSnake.body[0].cordY=10;
    //initialize element 1
    sSnake.body[1].cordX=9;
    sSnake.body[1].cordY=10;
    //initialize element 2
    sSnake.body[2].cordX=8;
    sSnake.body[2].cordY=10;
    //initialize element 3
    sSnake.body[3].cordX=7;
    sSnake.body[3].cordY=10;
    //initialize element 4
    sSnake.body[4].cordX=6;
    sSnake.body[4].cordY=10;
    
    sSnake.size=5;
    sSnake.is_initialized=1;
  }else{
    if(key==UP){
      cout << "Key up pressed, or still moving up" << endl;
      refreshSnake(-1,(sSnake.body[0].cordY+1));
    }else if(key==DOWN){
      cout << "Key down pressed, or still moving down" << endl;
      refreshSnake(-1,(sSnake.body[0].cordY-1));
    }else if(key==LEFT){
      cout << "Key left pressed, or still moving left" << endl;
      refreshSnake((sSnake.body[0].cordX-1),-1);
    }else if(key==RIGHT){
      cout << "Key right pressed, or still moving right" << endl;
      refreshSnake((sSnake.body[0].cordX+1),+1);
    }else if(key==ESCAPE){
      cout << "Key escape pressed, exiting..." << endl;
      refreshSnake(99999,-1); // Refresh the snakehead to a position which is way out of screen, so it exits
    }
  }
  
}
// Subroutine for the movesnake function, this makes a new head and cycles the whole snake
void refreshSnake(int newheadX, int newheadY){
  
  Snake tempSnake;
  
  //REFRESH THE HEAD OF THE SNAKE
  if(newheadX==-1){ // The head must be moved in the Y axis
    // move the new head
    tempSnake.body[0].cordY=newheadY;
    tempSnake.body[0].cordX=sSnake.body[0].cordX;
  }else if(newheadY==-1){ // The head must be moved in the X axis
    tempSnake.body[0].cordX=newheadX;
    tempSnake.body[0].cordY=sSnake.body[0].cordY;
  }
  
  // REFRESH THE REST OF THE BODY
  // Move the rest of the elements behind the new head, except the last one that gets deleted
  for(int count_elements=0;count_elements<(sSnake.size-1);count_elements++){
   tempSnake.body[count_elements+1]=sSnake.body[count_elements];
  }
    // If the last one had food it shall survive and make the snake longer
  if(sSnake.body[sSnake.size-1].food==1){
    tempSnake.body[sSnake.size]=sSnake.body[sSnake.size-1];
    tempSnake.body[sSnake.size].food=0;
    sSnake.size+=1;
  }
    //refresh the whole snake and replace all the elements
  for(int i=0;i<sSnake.size;i++){
    sSnake.body[i]=tempSnake.body[i];
  }
  
}

// This function checks the hitdetection if the snake hit an apple (update the whole snake) or a wall
int hitDetect(){
  int snake_dead=0;
  // Check if the snake is initialized and if its between its boundries.
  cout << "Checking if the snakehead collided or if the snake is not initialized yet...\n" << endl;
  
  // Checking if the snake has hit its own tail
  for(int elements_counted=1;elements_counted<sSnake.size;elements_counted++){
    if(sSnake.body[elements_counted].cordX==sSnake.body[0].cordX && sSnake.body[elements_counted].cordY==sSnake.body[0].cordY){
      sSnake.is_initialized=0; // A bit of an hack and slash solution, but it works.
    }
  }
  
  if(sSnake.is_initialized==0 || 
    sSnake.body[0].cordX<0 || sSnake.body[0].cordX>=SCREEN_X_SIZE || // Check X value of the head
    sSnake.body[0].cordY<0 || sSnake.body[0].cordY>=SCREEN_Y_SIZE // Check Y value of the head
    ){
    snake_dead=1;
    cout << "The snake died!" << endl;
  }else{ // Check for the food, add points and add new segment (food)
      cout << "Checking if the snakehead found some food..." << endl;
      if(sSnake.body[0].cordX==sPieceofcake.cordX && sSnake.body[0].cordY==sPieceofcake.cordY){
	cout << "Food found at coordinates {" << sPieceofcake.cordX << ";" <<sPieceofcake.cordY << "}" << endl;
	sSnake.score+=SCOREPOINT; // add score to the total
	sSnake.body[0].food=1; // Update the head that it now has food inside of it
	sPieceofcake.does_exist=0; // Update the piece of cake because it has been eaten
      }
  }
  return snake_dead;
}

// This function checks if the fruit is still present and otherwise randomnizes its position and replaces it
void spawnFood(){
  if(sPieceofcake.does_exist==0){
    cout << "Piece of cake is no more! generating a new one..." << endl;
    int goodCoords=0;
    int randX;
    int randY;
    
    do{
      goodCoords=1;
      
      srand ((time(NULL)<<3)*4); // Create new random factors and assign them to a temporary variable between bounds.
      randX=rand() % SCREEN_X_SIZE;
      cout << "New X coordinate generated: " << randX << endl;
      srand ((time(NULL)*2+550)>>3);
      randY=rand() % SCREEN_Y_SIZE;
      cout << "New Y coordinate generated: " << randY << endl;
      
      cout << "Scanning body elements: ";
	for(int elements=0;elements<sSnake.size;elements++){ // Cycle through all the snake bodys elements and check if the piece of cake overlaps
	  cout << elements;
	  if(sSnake.body[elements].cordX==randX && sSnake.body[elements.cordY]==randY){
	    goodCoords=0;
	    cout << "\nCollision found! Trying new coordinates..." << endl;
	  }
	}
	  
    }while(goodCoords==0); // Do the loop till we have a good placement for the cake
    cout << "Coordinates pass the tests, assigning them to the POC" << endl;
    // Place the new piece of cake
    sPieceofcake.cordX=randX;
    sPieceofcake.cordY=randY;
  }
}

